﻿using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Windows.Media.Imaging;
using System.Drawing;

namespace DrawImage
{
    public partial class DrawImageForm : Form
    {
        public DrawImageForm()
        {
            InitializeComponent();

            SetStyle(ControlStyles.OptimizedDoubleBuffer
                     | ControlStyles.ResizeRedraw
                     | ControlStyles.Selectable
                     | ControlStyles.AllPaintingInWmPaint
                     | ControlStyles.UserPaint
                     | ControlStyles.SupportsTransparentBackColor,
                     true);

            this.menuStrip.BackColor = Color.FromArgb(238, 238, 242);
            this.toolStrip.BackColor = Color.FromArgb(238, 238, 242);
            this.splitter1.BackColor = Color.FromArgb(238, 238, 242);
            this.statusStrip1.BackColor = Color.FromArgb(238, 238, 242);

            this.imagesTreeView.BackColor = Color.FromArgb(245, 245, 245);
            this.picturePanel.BackColor = Color.FromArgb(245, 245, 245);

            pictureBox.MouseWheel += pictureBox_MouseWheel;
            pictureBox.MouseDown += pictureBox_MouseDown;
            pictureBox.MouseMove += pictureBox_MouseMove;
            pictureBox.MouseUp += pictureBox_MouseUp;
        }

        #region 字段

        MouseFn mouseFn = MouseFn.MovePicture;
        Graphics graphicsFromImage;
        Graphics graphicsFromPictureBox;

        Bitmap bitMask;
        Bitmap bitImage;

        Boolean isDrawing;
        PointF startPoint;

        //关于放大与缩小的变量
        private const float zoomRatio = 2f;

        //保存MASK的文件名
        string saveMaskFileName;
        //擦除颜色值
        Color eraseColor = ColorTranslator.FromHtml("#00000000");

        string rootNodePath; // 保存用户选择的文件夹路径
        InfoForm infoForm;

        #endregion 字段

        #region pictureBox 鼠标事件响应
        PointF currentPoint;
        List<object> imageBackupList = new List<object>();
        private void pictureBox_MouseEnter(object sender, EventArgs e)
        {
            pictureBox.Focus();
        }

        private void pictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left) {
                switch (mouseFn) {
                    case MouseFn.MovePicture: {
                        if (pictureBox.Image != null) {
                            Cursor = Cursors.SizeAll;
                            startPoint = e.Location;
                        }
                        break;
                    }
                    case MouseFn.DrawCurve: {
                        startPoint = pointToPicture(e.Location);
                        imageBackupList.Add(pictureBox.Image.Clone());
                        if (imageBackupList.Count > 3) {
                            imageBackupList.RemoveAt(0);
                        }
                        graphicsFromImage = Graphics.FromImage(pictureBox.Image);
                        toolStripButton10.Enabled = true;
                        isDrawing = true;
                        break;
                    }
                    case MouseFn.DrawPolyline: {
                        startPoint = new PointF(e.X, e.Y);
                        imageBackupList.Add(pictureBox.Image.Clone());
                        if (imageBackupList.Count > 3) {
                            imageBackupList.RemoveAt(0);
                        }
                        graphicsFromImage = Graphics.FromImage(pictureBox.Image);
                        graphicsFromPictureBox = pictureBox.CreateGraphics();
                        toolStripButton10.Enabled = true;
                        isDrawing = true;
                        break;
                    }
                    case MouseFn.Measure: {
                        startPoint = new PointF(e.X, e.Y);
                        graphicsFromPictureBox = pictureBox.CreateGraphics();
                        isDrawing = true; ;
                        pictureBox.Refresh();
                        break;
                    }
                    case MouseFn.Erase: {
                        startPoint = pointToPicture(new PointF(e.X, e.Y));
                        imageBackupList.Add(pictureBox.Image.Clone());
                        if (imageBackupList.Count > 3) {
                            imageBackupList.RemoveAt(0);
                        }
                        graphicsFromPictureBox = pictureBox.CreateGraphics();
                        toolStripButton10.Enabled = true;
                        isDrawing = true;
                        break;
                    }
                    default:
                        break;
                }
            }
        }

        private void pictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left) {
                switch (mouseFn) {
                    case MouseFn.MovePicture: {
                        if (pictureBox.Image != null) {
                            int deltaX = e.X - (int)startPoint.X;
                            int deltaY = e.Y - (int)startPoint.Y;
                            pictureBox.Location = new Point(pictureBox.Location.X + deltaX, pictureBox.Location.Y + deltaY);
                        }
                        break;
                    }
                    case MouseFn.DrawCurve: {
                        if (isDrawing) {
                            currentPoint = new PointF(e.X, e.Y);
                            currentPoint = pointToPicture(currentPoint);
                            graphicsFromImage.SmoothingMode = SmoothingMode.HighQuality;
                            graphicsFromImage.DrawLine(new Pen(Color.Red, 2), startPoint, currentPoint);
                            startPoint = currentPoint;
                            pictureBox.Refresh();
                            // Point currentPoint = new Point(e.X, e.Y);
                            // Point currentPoint = pictureBoxMask.PointToClient(panelPic.PointToScreen(e.Location));
                            // PointF currentPoint = pictureBoxMask.PointToClient(Control.MousePosition);
                            //pictureBoxMask.Image = bitMask;
                        }
                        break;
                    }
                    case MouseFn.DrawPolyline: {
                        if (isDrawing) {
                            pictureBox.Refresh();
                            currentPoint = new PointF(e.X, e.Y);
                            graphicsFromPictureBox.SmoothingMode = SmoothingMode.HighQuality;
                            graphicsFromPictureBox.DrawLine(new Pen(Color.Blue, 2), startPoint, currentPoint);
                        }
                        break;
                    }
                    case MouseFn.Measure: {
                        if (isDrawing) {
                            pictureBox.Refresh();
                            currentPoint = e.Location;
                            double srcK = (currentPoint.Y - startPoint.Y) / (currentPoint.X - startPoint.X);
                            double tarK = -1 / srcK;

                            PointF startPoint1 = new PointF();
                            PointF endPoint1 = new PointF();
                            PointF startPoint2 = new PointF();
                            PointF endPoint2 = new PointF();

                            if (tarK > -128 && tarK < 128) {
                                // k1 * k2 = -1
                                // sin2a + cos2a = 1
                                // tana = sina / cosa
                                double deltaX = Math.Sqrt(1d / (1 + tarK * tarK)) * 20;

                                double tarB1 = startPoint.Y - tarK * startPoint.X;
                                double tarB2 = currentPoint.Y - tarK * currentPoint.X;

                                // y = ax + b 计算两个点的坐标
                                float s1Y1 = (float)((startPoint.X - deltaX) * tarK + tarB1);
                                float s1Y2 = (float)((startPoint.X + deltaX) * tarK + tarB1);

                                float s2Y1 = (float)((currentPoint.X - deltaX) * tarK + tarB2);
                                float s2Y2 = (float)((currentPoint.X + deltaX) * tarK + tarB2);

                                startPoint1 = new PointF((float)(startPoint.X - deltaX), s1Y1);
                                endPoint1 = new PointF((float)(startPoint.X + deltaX), s1Y2);

                                startPoint2 = new PointF((float)(currentPoint.X - deltaX), s2Y1);
                                endPoint2 = new PointF((float)(currentPoint.X + deltaX), s2Y2);
                            }
                            else {
                                startPoint1 = new PointF(startPoint.X, startPoint.Y - 20);
                                endPoint1 = new PointF(startPoint.X, startPoint.Y + 20);
                                startPoint2 = new PointF(currentPoint.X, currentPoint.Y - 20);
                                endPoint2 = new PointF(currentPoint.X, currentPoint.Y + 20);
                            }

                            graphicsFromPictureBox.SmoothingMode = SmoothingMode.HighQuality;

                            var pen = new Pen(Color.Blue, 2);
                            graphicsFromPictureBox.DrawLine(pen, startPoint, currentPoint);
                            graphicsFromPictureBox.DrawLine(pen, startPoint1, endPoint1);
                            graphicsFromPictureBox.DrawLine(pen, startPoint2, endPoint2);
                        }
                        break;
                    }
                    case MouseFn.Erase: {
                        if (isDrawing) {
                            //currentPoint = pointToPicture(currentPoint);
                            currentPoint = pointToPicture(new PointF(e.X, e.Y));
                            int tempX = (int)currentPoint.X;
                            int tempY = (int)currentPoint.Y;

                            int width = 10 * (pictureBox.Image.Height / pictureBox.Height);
                            for (int i = tempX - width; i < tempX + width; i++) {
                                for (int j = tempY - width; j < tempY + width; j++) {
                                    if (i > pictureBox.Image.Width || i < 0 ||
                                        j > pictureBox.Image.Height || j < 0) {
                                        continue;
                                    }
                                    try { (pictureBox.Image as Bitmap).SetPixel(i, j, eraseColor); } catch { }
                                }
                            }
                            pictureBox.Refresh();
                        }
                        break;
                    }
                }
            }
        }

        private void pictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left) {
                switch (mouseFn) {
                    case MouseFn.MovePicture: {
                        Cursor = Cursors.Default;
                        break;
                    }
                    case MouseFn.DrawCurve: {
                        isDrawing = false;
                        break;
                    }
                    case MouseFn.DrawPolyline: {
                        var endPoint = new PointF(e.X, e.Y);
                        endPoint = pointToPicture(endPoint);
                        startPoint = pointToPicture(startPoint);
                        pictureBox.Refresh();
                        graphicsFromImage.SmoothingMode = SmoothingMode.HighQuality;
                        graphicsFromImage.DrawLine(new Pen(Color.Red, 2), startPoint, endPoint);
                        pictureBox.Refresh();
                        isDrawing = false;
                        break;
                    }
                    case MouseFn.Measure: {
                        var endPoint = new PointF(e.X, e.Y);
                        if (startPoint == endPoint) {
                            break;
                        }
                        var tempStart = pointToPicture(startPoint);
                        var tempCurrent = pointToPicture(endPoint);

                        int x = (int)Math.Abs(tempStart.X - tempCurrent.X);
                        int y = (int)Math.Abs(tempStart.Y - tempCurrent.Y);
                        double len = Math.Sqrt(x * x + y * y);
                        graphicsFromPictureBox.DrawString("长度=" + len.ToString("0.0"),
                            new Font(FontFamily.GenericMonospace, 12f),
                            new SolidBrush(Color.Lime), e.Location);
                        isDrawing = false;
                        break;
                    }
                    case MouseFn.Erase: {
                        isDrawing = false;
                        break;
                    }
                }
            }
        }

        private void pictureBox_MouseWheel(object sender, MouseEventArgs e)
        {
            if (pictureBox.Image == null)
                return;
            if (e.Delta >= 0) {
                if (pictureBox.Width >= pictureBox.Image.Width && pictureBox.Height >= pictureBox.Image.Height)
                    return;
                int deltaX = (int)(e.X * (zoomRatio - 1.0));
                int deltaY = (int)(e.Y * (zoomRatio - 1.0));

                pictureBox.Width = (int)(pictureBox.Width * zoomRatio);
                pictureBox.Height = (int)(pictureBox.Height * zoomRatio);
                pictureBox.Location = new Point(pictureBox.Location.X - deltaX, pictureBox.Location.Y - deltaY);
            }
            else {
                if (pictureBox.Width <= picturePanel.Width && pictureBox.Height <= picturePanel.Height)
                    return;
                int deltaX = (int)(e.X * (1.0 - 1.0 / zoomRatio));
                int deltaY = (int)(e.Y * (1.0 - 1.0 / zoomRatio));

                pictureBox.Width = (int)(pictureBox.Width / zoomRatio);
                pictureBox.Height = (int)(pictureBox.Height / zoomRatio);
                pictureBox.Location = new Point(pictureBox.Location.X + deltaX, pictureBox.Location.Y + deltaY);

                if (pictureBox.Width <= picturePanel.Width && pictureBox.Height <= picturePanel.Height) {
                    int locationX = picturePanel.ClientSize.Width / 2 - pictureBox.Width / 2;//picturePanel.Location.X + 
                    int locationY = picturePanel.ClientSize.Height / 2 - pictureBox.Height / 2;//picturePanel.Location.Y + 
                    pictureBox.Location = new Point(locationX, locationY);
                }
            }
            pictureBox.Refresh();
        }
        #endregion

        #region 工具栏按钮点击事件响应
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.MovePicture;
            pictureBox.Cursor = Cursors.Default;
        }

        /// <summary>
        /// 放大
        /// </summary>
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            if (pictureBox.Image == null)
                return;
            if (pictureBox.Width >= pictureBox.Image.Width && pictureBox.Height >= pictureBox.Image.Height)
                return;
            pictureBox.Focus();
            pictureBox.Width = (int)(pictureBox.Width * zoomRatio);
            pictureBox.Height = (int)(pictureBox.Height * zoomRatio);
        }

        /// <summary>
        /// 缩小
        /// /// </summary>
        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            pictureBox.Focus();
            if (pictureBox.Image == null)
                return;
            if (pictureBox.Width <= picturePanel.Width && pictureBox.Height <= picturePanel.Height)
                return;
            pictureBox.Width = (int)(pictureBox.Width / zoomRatio);
            pictureBox.Height = (int)(pictureBox.Height / zoomRatio);
            if (pictureBox.Width <= picturePanel.Width && pictureBox.Height <= picturePanel.Height) {
                int locationX = picturePanel.ClientSize.Width / 2 - pictureBox.Width / 2;
                int locationY = picturePanel.ClientSize.Height / 2 - pictureBox.Height / 2;
                pictureBox.Location = new Point(locationX, locationY);
            }
        }

        /// <summary>
        /// 标注
        /// </summary>
        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.DrawCurve;   // 标注
            pictureBox.Cursor = new Cursor(this.GetType(), "pen.cur");//./Assets/pen.cur
            toolStripButton10.Enabled = false;
            imageBackupList.Clear();
        }

        /// <summary>
        /// 测量
        /// </summary>
        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.Measure;//测量
            pictureBox.Cursor = Cursors.Cross;
        }

        private void toolStripButton6_Click(object sender, EventArgs e)
        {
            保存ToolStripMenuItem_Click(sender, e);
        }

        /// <summary>
        /// 擦除
        /// </summary>
        private void toolStripButton7_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.Erase;
            pictureBox.Cursor = new Cursor(this.GetType(), "eraser.cur");
            toolStripButton10.Enabled = false;
            imageBackupList.Clear();
        }

        /// <summary>
        /// 删除选中节点
        /// </summary>
        private void toolStripButton8_Click(object sender, EventArgs e)
        {
            if (imagesTreeView.SelectedNode == null) {
                return;
            }
            var parentNode = imagesTreeView.SelectedNode.Parent;
            if (parentNode == null) {
                for (int i = 0; i < imagesTreeView.Nodes.Count; i++) {
                    var node = imagesTreeView.Nodes[i];
                    if (node == null) {
                        continue;
                    }
                    if (node.Checked) {
                        node.Remove();
                        i--;
                    }
                }
                return;
            }
            for (int i = 0; i < parentNode.Nodes.Count; i++) {
                var node = parentNode.Nodes[i];
                if (node == null) {
                    continue;
                }
                if (node.Name.Equals(displayingImageName)) {
                    erasePicture();
                }
                if (node.Checked) {
                    node.Remove();
                    i--;
                }
            }
            toolStripButton8.Enabled = false;
        }

        /// <summary>
        /// 折线标注
        /// </summary>
        private void toolStripButton9_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.DrawPolyline;   // 标注（画折线）
            pictureBox.Cursor = new Cursor(this.GetType(), "pen.cur");
            toolStripButton10.Enabled = false;
            imageBackupList.Clear();
        }

        /// <summary>
        /// 标注和擦除撤销
        /// </summary>
        private void toolStripButton10_Click(object sender, EventArgs e)
        {
            if (mouseFn == MouseFn.DrawCurve || mouseFn == MouseFn.DrawPolyline || mouseFn == MouseFn.Erase) {
                pictureBox.Image = imageBackupList.Last() as Bitmap;
                imageBackupList.Remove(imageBackupList.Last());
                if (imageBackupList.Count == 0) {
                    toolStripButton10.Enabled = false;
                    return;
                }
            }
        }

        #endregion

        #region 菜单栏按钮点击事件响应
        private void 打开ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dialog = new FolderBrowserDialog
            {
                Description = "请选择图片所在文件夹"
            };
            if (dialog.ShowDialog() == DialogResult.OK) {
                if (string.IsNullOrEmpty(dialog.SelectedPath)) {
                    MessageBox.Show(this, "文件夹路径不能为空！", "提示");
                    return;
                }
                rootNodePath = dialog.SelectedPath;
                var temp = rootNodePath.Split('\\');
                var nodeText = temp[temp.Length - 1];
                var rootNode = new TreeNode()
                {
                    Text = nodeText,
                    Name = dialog.SelectedPath,
                    Tag = "directory",
                    ImageIndex = 0
                };
                rootNode.Nodes.Add("");
                this.imagesTreeView.Nodes.Add(rootNode);
            }
        }

        private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try {
                Image img = pictureBox.Image;
                MemoryStream mfs = new MemoryStream();
                img.Save(mfs, ImageFormat.Png);
                //if (pictureBoxMask.Image != null) {
                //    Image image = pictureBoxMask.Image;
                //    img.Dispose();
                //    bitMask.Dispose();
                //    gMask.Dispose();
                //    pictureBoxMask.Image = null;
                //    image.Dispose();
                //    pictureBoxMask.Refresh();
                //}

                Image bmp1 = Image.FromStream(mfs);
                bmp1.Save(saveMaskFileName, ImageFormat.Png);

                bmp1?.Dispose();
                mfs?.Close();
                mfs?.Dispose();
                //  img.Dispose();
                MessageBox.Show("保存成功！");

                //FileStream fileStream = new FileStream(saveMaskFileName, FileMode.Open, FileAccess.Read);

                //int byteLength = (int)fileStream.Length;
                //byte[] fileBytes = new byte[byteLength];
                //fileStream.Read(fileBytes, 0, byteLength);
                ////文件流关閉,文件解除锁定
                //fileStream.Close();

                //Image imgMask = Image.FromStream(new MemoryStream(fileBytes));


                //// Image imgMask = Image.FromFile(strFullImagePath);
                ////  bitMask = new Bitmap(imgMask);
                /////////////////////////////////
                ////  Image imgMask = Image.FromFile(saveMaskFileName);
                //bitMask = new Bitmap(imgMask);
                //gMask = Graphics.FromImage(bitMask);
                //pictureBoxMask.BackColor = Color.Transparent;
                //pictureBoxMask.Parent = pictureBox;
                //pictureBoxMask.Image = imgMask;

            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
            }

        }

        private void 放大ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toolStripButton2_Click(sender, e);
        }

        private void 缩小ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toolStripButton3_Click(sender, e);
        }

        private void 拖动ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.MovePicture;// 拖动
            pictureBox.Cursor = Cursors.Default;
        }

        //private void 标注ToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    mouseFn = MouseFn.DrawCurve;   // 标注
        //    pictureBox.Cursor = new Cursor(this.GetType(), "pen.cur");
        //}

        private void 标注ToolStripMenuItem1_Click(object sender, EventArgs e) => toolStripButton4_Click(sender, e);

        private void 折线标注ToolStripMenuItem_Click(object sender, EventArgs e) => toolStripButton9_Click(sender, e);

        private void 擦除标注ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mouseFn = MouseFn.Erase;
            pictureBox.Cursor = new Cursor(this.GetType(), "eraser.cur");
        }

        private void DectectCrack(object upperCase)
        {
            string srcFileName = upperCase as string;
            string dstFileName = Path.GetDirectoryName(srcFileName) + "\\" + Path.GetFileNameWithoutExtension(srcFileName) + ".png";

            try {
                int ret = DLLAll.FindCracks(srcFileName, dstFileName, 255, 0, 0);
                this.Invoke(new MethodInvoker(delegate {
                    if (ret == 0) {
                        MessageBox.Show("检测裂缝完成");
                    }
                    else {
                        MessageBox.Show("检测失败！");
                    }
                }));
            }
            catch (Exception ex) {
                this.Invoke(new MethodInvoker(delegate {
                    MessageBox.Show(ex.Message);
                }));
            }
            this.Invoke(new MethodInvoker(delegate {
                infoForm.Thread_Time.Dispose();
                infoForm.Close();
                显示原图ToolStripMenuItem1_Click(null, null);
                显示裂缝ToolStripMenuItem_Click(null, null);
            }));
        }

        private void 检测裂缝ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string filePath = getPicturePath();
            if (filePath == null) {
                MessageBox.Show("未选中图片");
                return;
            }
            infoForm = new InfoForm("正在检测裂缝");
            Thread t = new Thread(DectectCrack);
            t.Start(filePath);
            infoForm.ShowDialog();
        }

        private void MeasureCrack(object upperCase)
        {
            string srcFileName = upperCase as string;
            string dstFileName = Path.GetDirectoryName(srcFileName) + "\\" + Path.GetFileNameWithoutExtension(srcFileName) + "_measure.png";
            try {
                int ret = DLLAll.MeasureCracks(srcFileName, dstFileName, 255, 0, 0);
                this.Invoke(new MethodInvoker(delegate {
                    if (ret == 0) {
                        MessageBox.Show("测量结束");
                    }
                    else {
                        MessageBox.Show("测量失败！");
                    }
                }));
            }
            catch (Exception ex) {
                this.Invoke(new MethodInvoker(delegate {
                    MessageBox.Show(ex.Message);
                }));
            }
            this.Invoke(new MethodInvoker(delegate {
                infoForm.Thread_Time.Dispose();
                infoForm.Close();
                显示原图ToolStripMenuItem1_Click(null, null);
                显示测量结果ToolStripMenuItem_Click(null, null);
            }));
        }

        private void 测量裂缝ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string fileName = getPicturePath();
            if (fileName == null) {
                MessageBox.Show("未选中图片");
                return;
            }
            string srcFileName = Path.GetDirectoryName(fileName) + "\\" + Path.GetFileNameWithoutExtension(fileName) + ".png";
            if (new FileInfo(srcFileName).Exists) {
                infoForm = new InfoForm("正在测量裂缝");
                Thread t = new Thread(MeasureCrack);
                t.Start(srcFileName);
                infoForm.ShowDialog();
            }
            else {
                MessageBox.Show("还没有检测裂缝");
            }
        }

        private void CrackFilterFun(object upperCase)
        {
            try {
                string srcFileName = (string)upperCase;
                int ret = DLLAll.Filter(srcFileName, srcFileName, 255, 0, 0);
                if (ret == 0) {
                    MessageBox.Show("滤波结束");
                }
                else {
                    MessageBox.Show("滤波失败！");
                }
                this.Invoke(new MethodInvoker(delegate {
                    infoForm.Thread_Time.Dispose();
                    infoForm.Close();
                    显示原图ToolStripMenuItem1_Click(null, null);
                    显示裂缝ToolStripMenuItem_Click(null, null);
                }));
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
            }
        }

        private void 图片滤波ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string fileName = getPicturePath();
            if (fileName == null) {
                MessageBox.Show("未选中图片");
                return;
            }
            string srcFileName = Path.GetDirectoryName(fileName) + "\\" + Path.GetFileNameWithoutExtension(fileName) + ".png";
            if (new FileInfo(srcFileName).Exists) {
                infoForm = new InfoForm("正在滤波");
                Thread t = new Thread(CrackFilterFun);
                t.Start(srcFileName);
                infoForm.ShowDialog();
            }
            else {
                MessageBox.Show("还没有检测裂缝");
            }
        }

        private void tIFF转JPEGToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Multiselect = true,
                RestoreDirectory = true,
                Filter = "TIFF文件 (*.tif)|*.tif",
                FilterIndex = 1
            };
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                infoForm = new InfoForm("正在转换");
                Thread t = new Thread(ImageTransformation);
                var parameters = new Dictionary<string, object>
                {
                    { "fileNames", openFileDialog.FileNames },
                    { "status", "fromTIFF" }
                };
                t.Start(parameters);
                infoForm.ShowDialog();
            }
        }

        private void 其它转TIFFToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Multiselect = true,
                RestoreDirectory = true,
                Filter = "图片文件 (*.*)|*.*",
                FilterIndex = 1
            };
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                infoForm = new InfoForm("正在转换");
                Thread t = new Thread(ImageTransformation);
                var parameters = new Dictionary<string, object>
                {
                    { "fileNames", openFileDialog.FileNames },
                    { "status", "toTIFF" }
                };
                t.Start(parameters);
                infoForm.ShowDialog();
            }
        }

        private void ImageTransformation(object parameters)
        {
            var tempDic = parameters as Dictionary<string, object>;
            var fileNames = tempDic["fileNames"] as string[];
            var status = tempDic["status"] as string;
            if (status == "fromTIFF") {
                foreach (var fileName in fileNames) {
                    using (var imageStreamSource = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
                        var decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                        Console.WriteLine("count=" + decoder.Frames.Count);
                        if (decoder.Frames.Count > 1) {
                            for (int i = 0; i < decoder.Frames.Count; i++) {
                                BitmapFrame bitmapSource = decoder.Frames[i];
                                string dstFilePath = Path.GetDirectoryName(fileName);
                                string dstFileName = dstFilePath + @"\" + Path.GetFileNameWithoutExtension(fileName) + i + ".jpg";
                                using (FileStream stream = new FileStream(dstFileName, FileMode.Create)) {
                                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                                    encoder.Frames.Add(bitmapSource);
                                    encoder.Save(stream);
                                }
                            }
                        }
                        else if (decoder.Frames.Count == 1) {
                            BitmapFrame bitmapSource = decoder.Frames[0];
                            string dstFilePath = Path.GetDirectoryName(fileName);
                            string dstFileName = dstFilePath + @"\" + Path.GetFileNameWithoutExtension(fileName) + ".jpg";
                            using (FileStream stream = new FileStream(dstFileName, FileMode.Create)) {
                                JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                                encoder.Frames.Add(bitmapSource);
                                encoder.Save(stream);
                            }
                        }
                    }
                }
            }
            else if (status == "toTIFF") {
                foreach (var fileName in fileNames) {
                    string dstFilePath = Path.GetDirectoryName(fileName);
                    string dstFileName = dstFilePath + @"\" + Path.GetFileNameWithoutExtension(fileName) + ".tif";
                    using (var stream = new FileStream(dstFileName, FileMode.Create)) {
                        TiffBitmapEncoder encoder = new TiffBitmapEncoder
                        {
                            Compression = TiffCompressOption.Zip
                        };
                        encoder.Frames.Add(BitmapFrame.Create(new Uri(fileName)));
                        encoder.Save(stream);
                    }
                }
            }
            this.Invoke(new MethodInvoker(delegate {
                infoForm.Thread_Time.Dispose();
                infoForm.Close();
                MessageBox.Show("转换结束");
            }));
        }

        private void 图片裁剪ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ImageCropResize ICRFrm = new ImageCropResize();
            ICRFrm.ShowDialog();
        }

        private void StitchMaping(object parameter)
        {
            string[] fileNames = parameter as string[];
            if (fileNames != null) {
                string srcFileNames = "";
                string dstFileName = "";
                foreach (var fileName in fileNames) {
                    srcFileNames += $"{fileName};";
                }
                dstFileName = Path.GetDirectoryName(fileNames[0]) + "\\" + "result.jpg";
                int flag = DLLAll.Stitcher(srcFileNames, dstFileName);
                if (flag == 0) {
                    this.Invoke(new MethodInvoker(delegate {
                        infoForm.Thread_Time.Dispose();
                        infoForm.Close();
                    }));
                    this.Invoke(new MethodInvoker(delegate {
                        MessageBox.Show("拼接成功");
                    }));
                }
                else {
                    this.Invoke(new MethodInvoker(delegate {
                        MessageBox.Show("拼接失败");
                    }));
                }
                this.Invoke(new MethodInvoker(delegate {
                    infoForm.Thread_Time.Dispose();
                    infoForm.Close();
                }));
            }
        }

        private void 图像拼接ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string[] fileNames = null;
            using (OpenFileDialog openFileDialog = new OpenFileDialog()) {
                openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                openFileDialog.FilterIndex = 1;
                openFileDialog.RestoreDirectory = false;
                openFileDialog.Multiselect = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK) {
                    fileNames = openFileDialog.FileNames;
                }
            }

            infoForm = new InfoForm("正在拼接");
            Thread t = new Thread(StitchMaping);
            t.Start(fileNames);
            infoForm.ShowDialog();
        }

        private void 显示原图ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (imagesTreeView == null || imagesTreeView.SelectedNode == null) {
                MessageBox.Show("未选中图片！");
                return;
            }
            displayingImageName = imagesTreeView.SelectedNode.Name;
            imageBackupList.Clear();
            mouseFn = MouseFn.MovePicture;

            #region 设置工具栏按钮的可用性
            toolStripStatusLabel2.Text = "显示状态：" + "原图";
            toolStripButton1.Enabled = true;
            toolStripButton2.Enabled = true;
            toolStripButton3.Enabled = true;
            toolStripButton8.Enabled = true;

            toolStripButton4.Enabled = false;
            toolStripButton5.Enabled = false;
            toolStripButton6.Enabled = false;
            toolStripButton7.Enabled = false;
            toolStripButton9.Enabled = false;
            toolStripButton10.Enabled = false;
            #endregion

            if (getPicturePath() == null) {
                MessageBox.Show("未选中图片");
                return;
            }
            Image img = Bitmap.FromFile(getPicturePath());
            bitImage = new Bitmap(Image.FromFile(getPicturePath()));
            pictureBox.Image = new Bitmap(bitImage.Width, bitImage.Height);
            pictureBox.BackgroundImage = img;
            pictureBox.BackgroundImageLayout = ImageLayout.Zoom;
            pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            pictureBox.Size = bitImage.Size;
            picturePanel.AutoScroll = false;
            this.DoubleBuffered = true;
        }

        private void 显示裂缝ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            #region 设置工具栏按钮的可用性
            toolStripButton1.Enabled = true;
            toolStripButton2.Enabled = true;
            toolStripButton3.Enabled = true;
            toolStripButton4.Enabled = true;
            toolStripButton5.Enabled = true;
            toolStripButton6.Enabled = true;
            toolStripButton7.Enabled = true;
            toolStripButton8.Enabled = true;
            toolStripButton9.Enabled = true;
            toolStripButton10.Enabled = true;
            标注ToolStripMenuItem.Enabled = true;
            擦除标注ToolStripMenuItem.Enabled = true;
            #endregion

            toolStripStatusLabel2.Text = "显示状态：" + "显示和修补";
            string filePath = displayingImageName;
            if (filePath == null) {
                return;
            }
            try {
                string strPath = Path.GetDirectoryName(filePath);
                string strFileImageName = Path.GetFileNameWithoutExtension(filePath);
                string strFullImagePath = strPath + "\\" + strFileImageName + ".png";
                saveMaskFileName = strFullImagePath;

                if (new FileInfo(strFullImagePath).Exists) {
                    Image imgMask = Image.FromFile(strFullImagePath);
                    bitMask = new Bitmap(imgMask);
                    pictureBox.Image = bitMask;
                    pictureBox.Refresh();
                    //graphicsFromImage = Graphics.FromImage(bitMask);
                }
            }
            catch {
                MessageBox.Show("文件错误");
                return;
            }
        }

        private void 显示测量结果ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            #region 设置工具栏按钮的可用性
            toolStripButton1.Enabled = true;
            toolStripButton2.Enabled = true;
            toolStripButton3.Enabled = true;
            toolStripButton8.Enabled = true;

            toolStripButton4.Enabled = true;
            toolStripButton5.Enabled = true;
            toolStripButton6.Enabled = false;
            toolStripButton7.Enabled = false;
            toolStripButton9.Enabled = true;
            toolStripButton10.Enabled = false;

            标注ToolStripMenuItem.Enabled = false;
            擦除标注ToolStripMenuItem.Enabled = false;
            #endregion

            toolStripStatusLabel2.Text = "显示状态：" + "测量结果";

            string filePath = getPicturePath();
            if (filePath == null) {
                return;
            }
            string strPath = Path.GetDirectoryName(filePath);
            string strFileImageName = Path.GetFileNameWithoutExtension(filePath);
            string fullFileName = strPath + "\\" + strFileImageName + "_measure.png";
            if (new FileInfo(fullFileName).Exists) {
                Image image = Image.FromFile(fullFileName);
                bitMask = new Bitmap(image);
                pictureBox.Image = bitMask;
                pictureBox.Refresh();
            }
            else {
                MessageBox.Show("还没有测量裂缝！");
            }
        }

        private void 清除图像ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string tarImageName = displayingImageName.Remove(displayingImageName.IndexOf('.')) + ".png";
            string tarImageName2 = displayingImageName.Remove(displayingImageName.IndexOf('.')) + "_measure" + ".png";
            File.Delete(tarImageName);
            File.Delete(tarImageName2);
            显示原图ContextMenuItem_Click(sender, e);
        }

        private void 数据录入ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new DataCRUD().ShowDialog();
        }

        PointF pointToPicture(PointF srcPoint)
        {
            //var scale = pictureBox.Image.Width / pictureBox.Width;
            return new PointF((float)((double)srcPoint.X * pictureBox.Image.Width / pictureBox.Width),
                (float)((double)srcPoint.Y * pictureBox.Image.Width / pictureBox.Width));
        }

        public void erasePicture()
        {
            if (pictureBox.Image != null) {
                Image image = pictureBox.Image;
                pictureBox.Image = null;
                image.Dispose();
                image = pictureBox.BackgroundImage;
                pictureBox.BackgroundImage = null;
                image.Dispose();
                pictureBox.Refresh();
            }
            bitImage?.Dispose();
            bitMask?.Dispose();
            graphicsFromImage?.Dispose();
            #region 重置工具栏按钮状态

            toolStripButton1.Enabled = false;
            toolStripButton2.Enabled = false;
            toolStripButton3.Enabled = false;
            toolStripButton4.Enabled = false;
            toolStripButton5.Enabled = false;
            toolStripButton6.Enabled = false;
            toolStripButton7.Enabled = false;
            toolStripButton8.Enabled = false;
            toolStripButton9.Enabled = false;
            toolStripButton10.Enabled = false;

            #endregion 重置工具栏按钮状态

            imageBackupList.Clear();
            mouseFn = MouseFn.MovePicture;
        }

        private string InputBox(string Caption, string Hint, string Default)
        {
            //by 闫磊 Email:Landgis@126.com,yanleigis@21cn.com 2007.10.10
            Form InputForm = new Form();
            InputForm.MinimizeBox = false;
            InputForm.MaximizeBox = false;
            InputForm.StartPosition = FormStartPosition.CenterScreen;
            InputForm.Width = 450;
            InputForm.Height = 200;
            //InputForm.Font.Name = "宋体";
            //InputForm.Font.Size = 10;

            InputForm.Text = Caption;
            Label lbl = new Label();
            lbl.Text = Hint;
            lbl.Left = 10;
            lbl.Top = 20;
            lbl.Parent = InputForm;
            lbl.AutoSize = true;
            TextBox tb = new TextBox();
            tb.Left = 30;
            tb.Top = 45;
            tb.Width = 300;
            tb.Parent = InputForm;
            tb.Text = Default;
            tb.SelectAll();
            Button btnok = new Button();
            btnok.Left = 30;
            btnok.Top = 80;
            btnok.Parent = InputForm;
            btnok.Text = "确定";
            InputForm.AcceptButton = btnok;//回车响应

            btnok.DialogResult = DialogResult.OK;
            Button btncancal = new Button();
            btncancal.Left = 120;
            btncancal.Top = 80;
            btncancal.Parent = InputForm;
            btncancal.Text = "取消";
            btncancal.DialogResult = DialogResult.Cancel;
            try {
                if (InputForm.ShowDialog() == DialogResult.OK) {
                    return tb.Text;
                }
                else {
                    return null;
                }
            }
            finally {
                InputForm.Dispose();
            }
        }

        #endregion

        #region 树形图和右键菜单

        int SelectedImagesCount = 0;
        string strechPathName;
        private void CountSelectedImages(TreeNodeCollection nodes)
        {
            foreach (TreeNode td in nodes) {
                if (td.Checked && (td.Tag as string).Equals("file")) {
                    SelectedImagesCount++;
                    strechPathName += td.Name;
                    strechPathName += ";";
                }
                if (td.Nodes.Count > 0)
                    CountSelectedImages(td.Nodes);
            }
        }

        public string getPicturePath()
        {
            return this.imagesTreeView.SelectedNode.Name;
        }

        private int getSelectedImagesCount()
        {
            SelectedImagesCount = 0;
            CountSelectedImages(imagesTreeView.Nodes);
            return SelectedImagesCount;
        }

        // 加载子节点
        private void imagesTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            e.Node.ImageIndex = 1;
            e.Node.Nodes.Clear();
            var dics = Directory.GetDirectories(e.Node.Name);
            foreach (string dic in dics) {
                var directoryInfo = new DirectoryInfo(dic);
                TreeNode subNode = new TreeNode(directoryInfo.Name)
                {
                    Name = directoryInfo.FullName,
                    Tag = "directory",
                    ImageIndex = 0
                };
                e.Node.Nodes.Add(subNode);
                subNode.Nodes.Add("");
            }
            var files = Directory.GetFiles(e.Node.Name);
            foreach (var file in files) {
                var fileInfo = new FileInfo(file);
                if (fileInfo.Extension.ToLower() == ".jpg" || fileInfo.Extension.ToLower() == ".bmp") {
                    var subNode = new TreeNode(fileInfo.Name)
                    {
                        Name = fileInfo.FullName,
                        Tag = "file"
                    };
                    if (IsImage(fileInfo.Extension.ToLower())) {
                        subNode.ImageIndex = 2;
                    }
                    else {
                        // 暂时设置为2，等到加入新图标后更改
                        subNode.ImageIndex = 2;
                    }
                    e.Node.Nodes.Add(subNode);
                }
            }
        }

        private bool IsImage(string extension)
        {
            if (extension.Equals(".jpg"))
                return true;
            if (extension.Equals(".png"))
                return true;
            if (extension.Equals(".bmp"))
                return true;
            return false;
        }

        // 双击节点时触发
        private string displayingImageName;     // 正在显示的图片
        private void imagesTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if ((e.Node.Tag as string).Equals("file")) {
                e.Node.Checked = true;
                imagesTreeView.SelectedNode = e.Node;
                显示原图ToolStripMenuItem1_Click(null, null);
                //显示原图(e.Node.Name);
            }
        }

        // 单击节点是触发
        private void imagesTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if ((e.Node.Tag as string).Equals("file")) {
                if (e.Button == MouseButtons.Right) {
                    Point pos = new Point(e.Node.Bounds.X + e.Node.Bounds.Width,
                        e.Node.Bounds.Y + e.Node.Bounds.Height / 2);
                    this.contextMenuTreeViewView.Show(this.imagesTreeView, pos);
                    this.imagesTreeView.SelectedNode = e.Node;
                }
                //else if (e.Button == MouseButtons.Left) {
                //    e.Node.Checked = !e.Node.Checked;
                //}
            }
        }

        private void 显示原图ContextMenuItem_Click(object sender, EventArgs e)
        {
            displayingImageName = this.imagesTreeView.SelectedNode.Name;
            显示原图ToolStripMenuItem1_Click(null, null);
        }

        private void 显示裂缝ContextMenuItem_Click(object sender, EventArgs e)
        {
            显示裂缝ToolStripMenuItem_Click(sender, e);
        }

        private void 长度测量ContextMenuItem_Click(object sender, EventArgs e) => 测量裂缝ToolStripMenuItem_Click(sender, e);

        private void 删除图像ContextMenuItem_Click(object sender, EventArgs e)
        {
            if (displayingImageName.Equals(imagesTreeView.SelectedNode.Name)) {
                erasePicture();
            }
            this.imagesTreeView.SelectedNode.Remove();
            清除图像ToolStripMenuItem_Click(sender, e);
        }

        private void 全选ContextMenuItem_Click(object sender, EventArgs e)
        {
            var parentNode = this.imagesTreeView.SelectedNode.Parent;
            parentNode.Checked = true;
            foreach (TreeNode node in parentNode.Nodes) {
                node.Checked = true;
            }
        }

        private void 取消全选ContextMenuItem_Click(object sender, EventArgs e)
        {
            var parentNode = this.imagesTreeView.SelectedNode.Parent;
            parentNode.Checked = false;
            foreach (TreeNode node in parentNode.Nodes) {
                node.Checked = false;
            }
        }

        private void imagesTreeView_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
        {
            e.Node.ImageIndex = 0;
        }

        private void imagesTreeView_AfterCheck(object sender, TreeViewEventArgs e)
        {
            imagesTreeView.SelectedNode = e.Node;
            toolStripButton8.Enabled = false;
            setDeleteEnable(imagesTreeView.Nodes);
        }

        private void setDeleteEnable(TreeNodeCollection nodes)
        {
            foreach (TreeNode td in nodes) {
                if (td.Checked) {
                    toolStripButton8.Enabled = true;
                    return;
                }
                if (td.Nodes.Count > 0)
                    setDeleteEnable(td.Nodes);
            }
        }

        #endregion

    }

    public class DLLAll
    {
        [DllImport("OpenCVTest.dll", EntryPoint = "FindCracks")]
        public static extern int FindCracks(string srcFileName, string dstFileName, int red, int green, int blue);

        [DllImport("OpenCVTest.dll", EntryPoint = "Filter")]
        public static extern int Filter(string srcFileName, string dstFileName, int red, int green, int blue);

        [DllImport("OpenCVTest.dll", EntryPoint = "MeasureCracks")]
        public static extern int MeasureCracks(string srcFileName, string dstFileName, int red, int green, int blue);

        [DllImport("OpenCVTest.dll", EntryPoint = "Stitcher")]
        public static extern int Stitcher(string srcFileNames, string dstFileNames);
    }

    public enum MouseFn
    {
        /// <summary>
        /// 移动图片
        /// </summary>
        MovePicture,
        /// <summary>
        /// 绘制曲线
        /// </summary>
        DrawCurve,
        /// <summary>
        /// 绘制直线
        /// </summary>
        DrawPolyline,
        /// <summary>
        /// 测量距离
        /// </summary>
        Measure,
        /// <summary>
        /// 擦除标注
        /// </summary>
        Erase
    }
}
